#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Project ：python_learning 
@File ：SingletonLogger.py
@IDE  ：PyCharm 
@Author ：李涵彬
@Date ：2024/4/11 上午11:01 
"""
import logging
from logging.handlers import RotatingFileHandler
from dotenv import load_dotenv
import os

# 假设这是你的文件名
FILE_NAME = "app.log"
# 定义常量来避免魔法数字/字符串
LOG_MAX_SIZE = int(os.getenv("LOG_MAX_SIZE", "1000000"))
LOG_BACKUP_COUNT = int(os.getenv("LOG_BACKUP_COUNT", "3"))


# 也可以考虑将这些配置项放到一个配置文件中，并在程序开始时读取

class SingletonLogger:
	_instance = None

	def __new__(cls, *args, **kwargs):
		"""
		实现单例模式的构造方法。
		该方法确保一个类只有一个实例，并且提供一个全局访问点来获得这个唯一实例。
		同时，该方法还负责初始化日志系统，包括从环境变量读取日志级别、格式、是否记录到文件以及文件路径，
		并根据这些配置设置日志记录的处理器。

		参数:
		- cls: 当前类的类对象。
		- *args: 位置参数，传递给类的构造函数。
		- **kwargs: 关键字参数，传递给类的构造函数。

		返回:
		- cls._instance: 当前类的单例实例。
		"""
		if cls._instance is None:
			cls._instance = super().__new__(cls)  # 创建类的实例
			load_dotenv()  # 加载环境变量配置

			# 从环境变量中读取并配置日志系统
			log_level = os.getenv("LOG_LEVEL", "INFO").upper()  # 日志级别，默认为INFO
			log_format = os.getenv("LOG_FORMAT", "%(asctime)s - %(levelname)s - %(filename)s - %(message)s")  # 日志格式，默认格式
			log_to_file = os.getenv("LOG_TO_FILE", "False").lower() in ["true", "1"]  # 是否记录到文件，默认不记录
			log_file_path = os.getenv("LOG_FILE_PATH", FILE_NAME)  # 日志文件路径，默认文件名

			cls._instance.logger = logging.getLogger(__name__)  # 获取日志记录器
			cls._instance.logger.setLevel(log_level)  # 设置日志级别

			formatter = logging.Formatter(log_format)  # 设置日志格式化器

			# 设置向控制台输出日志的处理器
			console_handler = logging.StreamHandler()  # 创建控制台处理器
			console_handler.setFormatter(formatter)  # 设置格式化器
			cls._instance.logger.addHandler(console_handler)  # 添加控制台处理器至日志记录器

			# 如果配置了记录到文件
			if log_to_file:
				try:
					file_handler = logging.handlers.RotatingFileHandler(
						log_file_path, maxBytes=LOG_MAX_SIZE, backupCount=LOG_BACKUP_COUNT
					)  # 创建文件处理器
					file_handler.setFormatter(formatter)  # 设置格式化器
					cls._instance.logger.addHandler(file_handler)  # 添加文件处理器至日志记录器
				except Exception as e:
					# 处理日志文件相关的异常，例如权限问题或磁盘空间不足
					cls._instance.logger.error(f"Failed to add file handler: {e}")
				# 根据情况考虑是否需要sys.exit()或者抛出异常

		return cls._instance  # 返回单例实例

	def info(self, message):
		"""
		记录一条信息级别的日志。

		参数:
		self -- 对象的自引用。
		message -- 需要记录的日志信息。

		返回值:
		无
		"""
		self.logger.info(message)  # 记录信息级别的日志

	def debug(self, message):
		"""
		向日志记录器发送一条调试信息。

		:param message: 要记录的调试信息。
		:type message: str
		:return: 无返回值。
		"""
		self.logger.debug(message)  # 使用logger实例的debug方法记录调试信息

	def warning(self, message):
		"""
		记录一条警告信息。

		参数:
		self -- 对象的自引用。
		message -- 需要记录的警告信息。

		返回值:
		无。
		"""
		self.logger.warning(message)  # 使用logger对象记录警告信息

	def error(self, message):
		"""
		记录错误信息。

		参数:
		self -- 对象的自引用。
		message -- 需要记录的错误信息。

		返回值:
		无。
		"""
		self.logger.error(message)  # 使用logger对象记录错误信息

	def critical(self, message):
		"""
		记录一条关键级别的日志信息。

		参数:
		- self: 对象自身的引用。
		- message: 需要记录的日志信息。

		返回值:
		无
		"""
		self.logger.critical(message)  # 记录一条关键级别的日志


if __name__ == "__main__":
	logger = SingletonLogger()
	logger.info("This is an info message")
	logger.debug("This is a debug message")
	logger.warning("This is a warning message")
	logger.error("This is an error message")
	logger.critical("This is a critical message")
